'use strict';
const path = require('path')
const pkgDir = require('pkg-dir').sync
const pathExists = require('path-exists').sync
const fse = require('fs-extra')
const npmInstall = require('npminstall')
const {isObject} = require('@hjx-cli-lerna/utils')
const formatPath = require('@hjx-cli-lerna/format-path')
const { getDefaultRegistry, getNpmLatestVersion } = require('@hjx-cli-lerna/get-npm-info')
class Package{
  constructor(options) {
    if(!options) throw new Error('Package类的options参数不能为空！');
    if(!isObject(options)) throw new Error('Package类的options不是一个Object对象')
    //package目标的路径
    this.targetPath = options.targetPath;
    //缓存package的路径
    this.storeDir = options.storeDir;
    //package的name
    this.packageName = options.packageName;
    //package的version
    this.packageVersion = options.packageVersion;
    //package的缓存目录前缀
    this.cacheFilePathPrefix = this.packageName.replace('/', '_')
  }

  get cacheFilePath() {
    return path.resolve(this.storeDir, `_${this.cacheFilePathPrefix}@${this.packageVersion}@${this.packageName}`);
  }

  getSpecificCacheFilePath(packageVersion){
    return path.resolve(this.storeDir, `_${this.cacheFilePathPrefix}@${packageVersion}@${this.packageName}`);
  }

  async prepare(){
    //缓存目录不存在时创建目录
    if(this.storeDir && !pathExists(this.storeDir)){
      fse.mkdirpSync(this.storeDir);
    }
    //获取最新的版本
    if(this.packageVersion === 'latest'){
      this.packageVersion = await getNpmLatestVersion(this.packageName);
    }
  }

  //判断当前package是否存在
  async exists(){
    if(this.storeDir){
      await this.prepare()
      return pathExists(this.cacheFilePath)
    }else {
     return pathExists(this.targetPath)
    }
  }

  //安装package
  async install(){
    await this.prepare();
    npmInstall({
      root: this.targetPath,
      storeDir: this.storeDir,
      registry: getDefaultRegistry(),
      pkgs: [{
        name: this.packageName,
        version: this.packageVersion
      }]
    })
  }

  //更新package
  async update(){
    await this.prepare()
    //1、获取最新的npm模块版本号
    const latestPackageVersion = await getNpmLatestVersion(this.packageName)
    //2、查询最新版本号对应的路径是否存在
    const latestFilePath = this.getSpecificCacheFilePath(latestPackageVersion)
    //3、如果不存在，则直接安装最新版本
    if(!pathExists(latestFilePath)){
     await npmInstall({
        root: this.targetPath,
        storeDir: this.storeDir,
        registry: getDefaultRegistry(),
        pkgs: [{
          name: this.packageName,
          version: latestPackageVersion
        }]
      })
      this.packageVersion = latestPackageVersion
    }else {
      this.packageVersion = latestPackageVersion
    }
  }

  //获取入口文件的路径
  getRootFilePath(){
    function _getRootFile(targetPath){
      //1、获取package.json所在的目录
      const dir = pkgDir(targetPath)
      if(dir){
        //2、读取package.json
        const pkgFile = require(path.resolve(dir, 'package.json'))
        //3、寻找main
        if(pkgFile && pkgFile.main){
          //4、路径的兼容（macOS/windows）
          return formatPath(path.resolve(dir, pkgFile.main));
        }
      }
      return null
    }
    if(this.storeDir){
      return _getRootFile(this.cacheFilePath);
    }else {
      return _getRootFile(this.targetPath);
    }

  }
}
module.exports = Package;
